use tauri::{
    ipc::InvokeError,
};
use std::process::Command;
use crate::models::{Word, DictationConfig};
use crate::parser::{parse_csv, parse_txt};
use crate::state::AppState;
use tauri::State;

// Commands that will be available to the frontend

#[tauri::command]
pub fn load_sample_words(file_type: &str) -> Result<Vec<Word>, InvokeError> {
    println!("加载示例词库，文件类型: {}", file_type);
    
    // 移除BOM和其他特殊字符，确保数据干净
    let content = if file_type == "csv" {
        "apple,苹果
book,书
computer,电脑
water,水
house,房子
car,汽车
school,学校
teacher,老师
student,学生
english,英语
chinese,中文
music,音乐
sport,运动
food,食物
friend,朋友
family,家庭
happy,快乐
beautiful,美丽的
difficult,困难的
important,重要的"
    } else {
        "apple [苹果;苹果树;苹果公司]
book [书;书籍;预定]
computer [电脑;计算机]
water [水;水域;海域]
house [房子;住宅;议院]
car [汽车;轿车;车厢]
school [学校;学院;学派]
teacher [老师;教师;导师]
student [学生;学者;研究人员]
english [英语;英文]
chinese [中文;中国的;中国人]
music [音乐;乐曲]
sport [运动;体育]
food [食物;食品]
friend [朋友;赞助人]
family [家庭;家族;亲属]
happy [快乐;高兴;乐意]
beautiful [美丽的;漂亮的;美好的]
difficult [困难的;艰难的;复杂的]
important [重要的;重大的;有势力的]"
    };

    let result = if file_type == "csv" {
        parse_csv(content).map_err(|e| InvokeError::from(e.to_string()))
    } else {
        parse_txt(content).map_err(|e| InvokeError::from(e.to_string()))
    };
    
    if let Ok(words) = &result {
        println!("成功加载 {} 个示例单词", words.len());
    } else {
        println!("加载示例词库失败");
    }
    
    result
}

#[tauri::command]
pub fn parse_file_content(content: &str, file_type: &str) -> Result<Vec<Word>, InvokeError> {
    if file_type == "csv" {
        parse_csv(content).map_err(|e| InvokeError::from(e.to_string()))
    } else {
        parse_txt(content).map_err(|e| InvokeError::from(e.to_string()))
    }
}

#[tauri::command]
pub fn update_config(state: State<AppState>, config: DictationConfig) -> Result<(), InvokeError> {
    let mut dictation_state = state.dictation_state.lock().unwrap();
    dictation_state.config = config;
    Ok(())
}

#[tauri::command]
pub fn get_current_word(state: State<AppState>) -> Result<Word, InvokeError> {
    let dictation_state = state.dictation_state.lock().unwrap();
    if dictation_state.words.is_empty() {
        return Err(InvokeError::from("词库为空".to_string()));
    }
    Ok(dictation_state.words[dictation_state.current_index].clone())
}

#[tauri::command]
pub fn speak_word(state: State<AppState>, word: &str) -> Result<(), InvokeError> {
    let dictation_state = state.dictation_state.lock().unwrap();
    let config = &dictation_state.config;
    
    println!("尝试朗读单词: {}, 配置: rate={}, volume={}", word, config.rate, config.volume);
    
    // Using system TTS for text-to-speech
    #[cfg(any(target_os = "linux", target_os = "macos"))]
    {
        // This is a simple implementation - in a real app you might want to use a more robust TTS library
        // Note: This requires espeak to be installed on the system
        let output = Command::new("espeak")
            .args(&[
                "-v", "en",
                "-s", &format!("{}", (config.rate * 100.0) as i32),
                "-a", &format!("{}", (config.volume * 100.0) as i32),
                word
            ])
            .output()
            .map_err(|e| format!("Failed to execute espeak: {}. Make sure espeak is installed on your system.", e))?;

        if !output.status.success() {
            eprintln!("espeak failed: {}", String::from_utf8_lossy(&output.stderr));
            return Err(InvokeError::from(format!("espeak failed: {}", String::from_utf8_lossy(&output.stderr))));
        }
    }
    
    #[cfg(target_os = "windows")]
    {
        let output = Command::new("powershell")
            .args(&[
                "-Command",
                &format!("Add-Type -AssemblyName System.Speech; $speak = New-Object System.Speech.Synthesis.SpeechSynthesizer; $speak.Rate = {}; $speak.Volume = {}; $speak.Speak('{}')", 
                    ((config.rate - 1.0) * 10.0) as i32, 
                    (config.volume * 100.0) as i32,
                    word)
            ])
            .output()
            .map_err(|e| format!("Failed to execute PowerShell: {}", e))?;

        if !output.status.success() {
            eprintln!("PowerShell failed: {}", String::from_utf8_lossy(&output.stderr));
            return Err(InvokeError::from(format!("PowerShell failed: {}", String::from_utf8_lossy(&output.stderr))));
        }
    }

    println!("成功朗读单词: {}", word);
    Ok(())
}

#[tauri::command]
pub fn next_word(state: State<AppState>) -> Result<usize, InvokeError> {
    let mut dictation_state = state.dictation_state.lock().unwrap();
    if dictation_state.words.is_empty() {
        return Err(InvokeError::from("词库为空".to_string()));
    }
    
    if dictation_state.config.random_mode {
        dictation_state.current_index = rand::random::<usize>() % dictation_state.words.len();
    } else {
        dictation_state.current_index = (dictation_state.current_index + 1) % dictation_state.words.len();
    }
    
    Ok(dictation_state.current_index)
}

#[tauri::command]
pub fn prev_word(state: State<AppState>) -> Result<usize, InvokeError> {
    let mut dictation_state = state.dictation_state.lock().unwrap();
    if dictation_state.words.is_empty() {
        return Err(InvokeError::from("词库为空".to_string()));
    }
    
    if dictation_state.current_index == 0 {
        dictation_state.current_index = dictation_state.words.len() - 1;
    } else {
        dictation_state.current_index -= 1;
    }
    
    Ok(dictation_state.current_index)
}

#[tauri::command]
pub fn set_current_index(state: State<AppState>, index: usize) -> Result<(), InvokeError> {
    let mut dictation_state = state.dictation_state.lock().unwrap();
    if index >= dictation_state.words.len() {
        return Err(InvokeError::from("索引超出范围".to_string()));
    }
    dictation_state.current_index = index;
    Ok(())
}

#[tauri::command]
pub fn get_progress(state: State<AppState>) -> Result<(usize, usize), InvokeError> {
    let dictation_state = state.dictation_state.lock().unwrap();
    Ok((dictation_state.current_index + 1, dictation_state.words.len()))
}

#[tauri::command]
pub fn reset_dictation(state: State<AppState>) -> Result<(), InvokeError> {
    let mut dictation_state = state.dictation_state.lock().unwrap();
    dictation_state.current_index = 0;
    dictation_state.is_playing = false;
    Ok(())
}

#[tauri::command]
pub fn set_playing(state: State<AppState>, playing: bool) -> Result<(), InvokeError> {
    let mut dictation_state = state.dictation_state.lock().unwrap();
    dictation_state.is_playing = playing;
    Ok(())
}